package com.shuangzh.brief.rpc;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.concurrent.atomic.AtomicLong;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.SmartLifecycle;

/**
 * RPC 客户端beanFactory. 生成客户端的代理对象，通过代理对象实现远程调用。
 * 
 * @author shuangzh
 *
 */
public class ClientProxyBeanFactory implements SmartLifecycle, FactoryBean {

	/**
	 * 服务端地址
	 */
	private String address = "127.0.0.1";

	/**
	 * 服务端的端口
	 */
	private int port = 9090;

	/**
	 * 远程调用的接口类
	 */
	private Class face;

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public Class getFace() {
		return face;
	}

	public void setFace(Class face) {
		this.face = face;
	}

	Socket socket = null;
	ObjectOutputStream out = null;
	ObjectInputStream in = null;
	AtomicLong id = new AtomicLong();

	class ProxyHandler implements InvocationHandler {

		public Object invoke(Object proxy, Method method, Object[] args)
				throws Throwable {

			RequestObject req = new RequestObject();
			
			req.setId(id.getAndIncrement());
			req.setMethodName(method.getName());
			// 设置调用方法的参数类型
			req.setParameterTypes(method.getParameterTypes());
			req.setArgs(args);

			out.writeObject(req);
			ResponseObject rsp = (ResponseObject) in.readObject();

			return rsp.getResult();
		}

	}

	public void start() {
		assert (address != null);
		assert (port != 0);
		assert (face != null);
		assert (face.isInterface());

		try {

			socket = new Socket(address, port);
			out = new ObjectOutputStream(socket.getOutputStream());
			in = new ObjectInputStream(socket.getInputStream());

		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public boolean isRunning() {
		// TODO Auto-generated method stub
		return false;
	}

	public void stop() {
		// TODO Auto-generated method stub

	}

	public int getPhase() {
		// TODO Auto-generated method stub
		return 0;
	}

	public Object getObject() throws Exception {
		return Proxy.newProxyInstance(this.getClass().getClassLoader(),
				new Class[] { face }, new ProxyHandler());
	}

	public Class getObjectType() {
		return face;
	}

	public boolean isSingleton() {
		// TODO Auto-generated method stub
		return false;
	}

	public boolean isAutoStartup() {
		// TODO Auto-generated method stub
		return false;
	}

	public void stop(Runnable arg0) {
		// TODO Auto-generated method stub

	}

	public static void main(String[] args) throws Exception {

		ClientProxyBeanFactory factory = new ClientProxyBeanFactory();
		// 设置代理接口
		factory.setFace(SimpleFace.class);
		// 初始化，以及启动socket链接
		factory.start();

		// 获取远程调用接口的代理对象
		SimpleFace sf = (SimpleFace) factory.getObject();

		for (int i = 0; i < 1000; i++) {
			System.out.println(sf.test());
			System.out.println(sf.test("yyyyy"));
		}
	}

}
